﻿using System;
using System.Reflection;
using System.Collections.Generic;

namespace UFrameWork
{
    /// <summary>
    /// 框架
    /// </summary>
    public class UWork
    {
        /// <summary>
        /// 日志标签
        /// </summary>
        public const string LogTag = "UWork";

        /// <summary>
        /// 命令关系表
        /// </summary>
        private Dictionary<string, UMethod> map = new Dictionary<string, UMethod>();

        /// <summary>
        /// 单例
        /// </summary>
        public static readonly UWork Instance = new UWork();

        /// <summary>
        /// 禁止外部实例化
        /// </summary>
        private UWork() { }

        /// <summary>
        /// 初始化框架
        /// </summary>
        /// <param name="log"></param>
        public void Init()
        {
            //初始化消息分发器
            UMsgDispatcher.Instance.Init();
        }

        /// <summary>
        /// 注册类实例
        /// </summary>
        /// <param name="obj">实例对象</param>
        /// <param name="isType">是否为Type类型注册</param>
        public void RegClass(object obj,bool isType = false)
        {
            Type oType = obj.GetType();
            if (isType) oType = (Type)obj;
            int order           = 0;
            string key          = string.Empty;
            object instance     = obj;
            bool isView         = oType.IsSubclassOf(typeof(UView));
            bool isController   = oType.IsSubclassOf(typeof(UController));

            if (isController)
            {
                instance = oType.Assembly.CreateInstance(oType.FullName);
            }

            MethodInfo[] methods = oType.GetMethods();

            object[] atts = null;

            foreach (MethodInfo m in methods)
            {
                if(isController)
                {
                    atts = m.GetCustomAttributes(typeof(UControllerAction), false);
                    if (atts == null || atts.Length == 0) continue;
                    UControllerAction action = (UControllerAction)atts[0];
                    key     = action.Name;
                    order   = action.Order;
                }

                if(isView)
                {
                    atts = m.GetCustomAttributes(typeof(UViewAction), false);
                    if (atts == null || atts.Length == 0) continue;
                    UViewAction action = (UViewAction)atts[0];
                    if ((isType && !m.IsStatic) || (!isType && m.IsStatic)) continue;
                    key = action.Name;
                    order = action.Order;
                }

                if (map.ContainsKey(key))
                {
                    map[key].Add(instance,m,order);
                }
                else
                {
                    map[key] = new UMethod(instance, m,order);
                }
            }
        }

        /// <summary>
        /// 注册程序集
        /// </summary>
        /// <param name="assembly">程序集</param>
        public void RegAssembly(Assembly assembly)
        {
            Type[] types = assembly.GetExportedTypes();

            foreach (Type type in types)
            {
                if (!type.IsSubclassOf(typeof(UController)) && !type.IsSubclassOf(typeof(UView)))
                    continue;
                RegClass(type,true);
            }
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="key">命令名称</param>
        /// <param name="objs">参数列表</param>
        /// <returns></returns>
        public void Do(string key, params object[] objs)
        {
            Invoke(key, objs);
        }

        /// <summary>
        /// 执行命令并返回结果
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="key">命令名称</param>
        /// <param name="objs">参数列表</param>
        /// <returns></returns>
        public T Do<T>(string key, params object[] objs)
        {
            return (T)Invoke(key, objs);
        }

        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="key">命令</param>
        /// <param name="objs">参数</param>
        /// <returns></returns>
        private object Invoke(string key, object[] objs)
        {
            if (map.ContainsKey(key))
            {
                return map[key].Invoke(objs);
            }
            return null;
        }

        /// <summary>
        /// 获取第一个方法的第一个参数类型
        /// </summary>
        /// <returns></returns>
        public Type GetMethodParamType(string key)
        {
            if (!map.ContainsKey(key))
            {
                return null;
            }
            return map[key].GetMethodParamType();
        }

        /// <summary>
        /// 日志记录
        /// </summary>
        /// <param name="obj">日志内容</param>
        /// <param name="level">日志级别</param>
        /// <param name="tag">标签</param>
        public void Log(object obj,LogLevel level = LogLevel.Debug,string tag = "Default")
        {
            Do(UEvent.LOG_WRITE, obj, level, tag);
        }
    }
}